package cn.tramy.pinxian.wind.eventstore.domain.model

import cn.tramy.pinxian.wind.eventstore.query.entry.DomainEventEntry
import com.alibaba.fastjson.JSON
import java.time.LocalDateTime

class DomainEvent(val uid: String, val payload: Any, val payloadType: Class<*>, val aggregateId: String, val aggregateType: Class<*>,
                  val createdAt: LocalDateTime = LocalDateTime.now(), val metaData: MutableMap<String, String> = mutableMapOf()) {

    fun entry(): DomainEventEntry {
        val payloadStr = JSON.toJSONString(payload)
        val aggregateTypeStr = this.aggregateType.name
        val metaDataStr = JSON.toJSONString(metaData)

        return DomainEventEntry(uid, payloadStr, payloadType.name, aggregateId, aggregateTypeStr, createdAt, metaDataStr)
    }

    fun addMetaData(key: String, value: String) {
        this.metaData[key] = value
    }

    companion object {
        fun build(entry: DomainEventEntry): DomainEvent {
            val aggregateType = Class.forName(entry.aggregateType)
            val payloadType = Class.forName(entry.payloadType)
            val payload = JSON.parseObject(entry.payload, payloadType)
            val metaData: MutableMap<String, String> = JSON.parseObject(entry.metaData, MutableMap::class.java) as MutableMap<String, String>
            return DomainEvent(entry.uid, payload, payloadType, entry.aggregateId, aggregateType, entry.createdAt, metaData)
        }
    }
}